from scopiavf.engine.rendertree import *
import scopiavf.engine.interactive as interactive
from chart import *

class TimeSlider(RenderSimpleTransformNode):
    def __init__( self, context, style, chart, common, involvedNodes = [] ):
        self.timemove = TimeSlider.Mover( self )
        self.windowresize = TimeSlider.Resizer( self )
        self.zoomin = TimeSlider.ZoomerIn( self )
        self.zoomout = TimeSlider.ZoomerOut( self )
        self.pan = TimeSlider.Pan( self )
        self.common = common
        self.involvedNodes = involvedNodes

        timeline = TimeLine(context, style, chart, self)
        timewindow = TimeWindow(context, style, self)
        self.timewindowT = RenderSimpleTransformNode(style, self, timewindow)
        comp = RenderComposeNode( context, style, [timeline, self.timewindowT] )
        RenderSimpleTransformNode.__init__(self, context, style, comp )
        self.startTime, self.endTime = timeline.marks[0], timeline.marks[-1]
        self.timerange = timeline.marks[-1] - timeline.marks[0]
        self.updateTime()
        self.set( (0,0,0), (0.8, 1, 1) )

    def updateTime(self):
        pos = 2.0*(self.common.timePos - self.startTime)/self.timerange - 1.0
        rad = 2.0 * self.common.timeRadius/self.timerange
        self.timewindowT.set( (pos, 0, 0), (rad, 1, 1) )
    
    class Mover(interactive.MouseHandler):
        "Timewindow motion mouse handler"
        button = 0
        def __init__( self, timeslider ):
            self.timeslider = timeslider

        def down(self, x, y):
            self.oldTimePos = self.timeslider.common.timePos
            # activate these two scene nodes for dynamic rendering
            position, self.dX, self.dY = self.timeslider.getLocalCoords( (x,y), 0 )
            self.timeslider.timewindowT.goDynamic()
            for node in self.timeslider.involvedNodes: node.goDynamic()

        def motion(self, oldpos, newpos, unitsperpix ):
            disp = ((newpos[0] - oldpos[0]) * self.dX + (newpos[1] - oldpos[1]) * self.dY)[0]
            timeperunit = (self.timeslider.timerange)/2.0
            self.timeslider.common.timePos =  disp * timeperunit + self.oldTimePos
            if self.timeslider.common.timePos < (self.timeslider.startTime - self.timeslider.common.timeRadius): 
                self.timeslider.common.timePos = self.timeslider.startTime - self.timeslider.common.timeRadius
            elif self.timeslider.common.timePos > (self.timeslider.endTime + self.timeslider.common.timeRadius): 
                self.timeslider.common.timePos = self.timeslider.endTime + self.timeslider.common.timeRadius
            self.timeslider.updateTime()

        def up(self, x, y):
            # disable these two scene nodes for dynamic rendering, 
            # render again with display list
            self.timeslider.timewindowT.goStatic()
            for node in self.timeslider.involvedNodes: node.goStatic()

    class Resizer(interactive.MouseHandler):
        "Timewindow scaling mouse handler"
        button = 0
        def __init__( self, timeslider ):
            self.timeslider = timeslider

        def down(self, x, y):
            # locate the shares circle in the scene tree
            self.oldTimeRadius = self.timeslider.common.timeRadius
            position, self.dX, self.dY = self.timeslider.getLocalCoords( (x,y), 0 )
            # activate these two scene nodes for dynamic rendering
            self.timeslider.timewindowT.goDynamic()
            for node in self.timeslider.involvedNodes: node.goDynamic()

        def motion(self, oldpos, newpos, unitsperpix ):
            disp = ((newpos[0] - oldpos[0]) * self.dX + (newpos[1] - oldpos[1]) * self.dY)[0]
            #disp = (newpos[0] - oldpos[0]) * unitsperpix / self.timeslider.scale[0]
            timeperunit = self.timeslider.timerange/2.0
            self.timeslider.common.timeRadius =  disp * timeperunit + self.oldTimeRadius
            if self.timeslider.common.timeRadius < self.timeslider.timerange*0.002: 
                self.timeslider.common.timeRadius = self.timeslider.timerange*0.002
            self.timeslider.updateTime()
        
        def up(self, x, y):
            # disablea these two scene nodes for dynamic rendering, 
            # render again with display list
            self.timeslider.timewindowT.goStatic()
            for node in self.timeslider.involvedNodes: node.goStatic()

    class ZoomerIn(interactive.MouseHandler):
        button = 3
        def __init__( self, timeslider ):
            self.timeslider = timeslider
        def down(self, x, y):
            self.timeslider.scale = ( self.timeslider.scale[0] * 1.1, 1, 1)
            self.timeslider.update()
    
    class ZoomerOut(interactive.MouseHandler):
        button = 4
        def __init__( self, timeslider ):
            self.timeslider = timeslider
        def down(self, x, y):
            self.timeslider.scale = ( self.timeslider.scale[0] * 0.9, 1, 1)
            self.timeslider.update()
    
    class Pan(interactive.MouseHandler):
        "Timewindow scaling mouse handler"
        button = 1
        def __init__( self, timeslider ):
            self.timeslider = timeslider

        def down(self, x, y):
            # activate dynamic rendering
            self.oldtrans = self.timeslider.translate
            self.timeslider.goDynamic()
            position, self.dX, self.dY = self.timeslider.parent.getLocalCoords( (x,y), 0 )

        def motion(self, oldpos, newpos, unitsperpix ):
            disp = ((newpos[0] - oldpos[0]) * self.dX + (newpos[1] - oldpos[1]) * self.dY)[0]
            #disp = (newpos[0] - oldpos[0]) * unitsperpix #/ self.timeline.parent.scale[0]
            self.timeslider.translate = ( self.oldtrans[0] + disp , self.oldtrans[1], self.oldtrans[2])
        
        def up(self, x, y):
            # disablea dynamic rendering, 
            # render again with display list
            self.timeslider.goStatic()

class TimeLine(RenderGeomNode):
    def __init__( self, context, style, chart, timeslider ):
        RenderGeomNode.__init__(self, context, style)
        self.marks = [ v[V_TIME] for v in chart.transactions ] # Should it be a numpy array?
        self.zoomin = timeslider.zoomin
        self.zoomout = timeslider.zoomout
        self.pan = timeslider.pan
    
    def renderAll(self):
        # render the timeline
        self.context.startCallback( self.zoomin )
        self.context.startCallback( self.zoomout )
        self.context.startCallback( self.pan )
        self.style.drawTimeLine( self.context, self )
        self.context.endCallback()
        self.context.endCallback()
        self.context.endCallback()


class TimeWindow(RenderGeomNode):
    def __init__( self, context, style, timeslider ):
        RenderGeomNode.__init__(self, context, style)
        self.timemove = timeslider.timemove
        self.windowresize = timeslider.windowresize
    
    def renderAll(self):
        # render the time window under the move callback
        self.context.startCallback( self.timemove )
        self.style.drawTimeLineWindow( self.context, self )
        self.context.endCallback()
        # render the time window resizer under the resize callback
        self.context.startCallback( self.windowresize )
        self.style.drawTimeLineWindowSizer( self.context, self )
        self.context.endCallback()
